package encrypting

import (
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"fmt"
	"os"
)

func Base64Encode(src []byte) []byte {
	return []byte(base64.StdEncoding.EncodeToString(src))
}

func Base64Decode(src []byte) ([]byte, error) {
	return base64.StdEncoding.DecodeString(string(src))
}

func TestBase64() {
	fmt.Println("base64 encoding...")
	hello := "你好，世界！hello world!"
	enbyte := Base64Encode([]byte(hello))
	fmt.Println(enbyte)

	debyte, err := Base64Decode(enbyte)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	if hello != string(debyte) {
		fmt.Println("hello is not equals to debyte")
		return
	}
	fmt.Println(string(debyte))
}

/*
Go语言的crypto里面支持对称加密的高级加解密包有：
crypto/aes包：AES(Advanced Encryption Standard)，又称Rijndael加密法，是美国联邦政府采用的一种区块加密标准。
crypto/des包：DES(Data Encryption Standard)，是一种对称加密标准，是目前使用最广泛的密钥系统，特别是在保护金融数据的安全中。曾是美国联邦政府的加密标准，但现已被AES所替代。
*/

var commonIV = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}

// key:32位长度
// aes.NewCipher(参数key必须是16、24或者32位的[]byte，分别对应AES-128, AES-192或AES-256算法)
func AesEncrypt(src, key string) []byte {
	// 创建加密算法aes
	c, err := aes.NewCipher([]byte(key))
	if err != nil {
		fmt.Printf("Error: NewCipher(%d bytes) = %s", len(key), err)
		os.Exit(-1)
	}
	plaintext := []byte(src)
	// 加密字符串
	cfb := cipher.NewCFBEncrypter(c, commonIV)
	ciphertext := make([]byte, len(plaintext))
	cfb.XORKeyStream(ciphertext, plaintext)
	fmt.Printf("%s=>%x\n", plaintext, ciphertext)
	return ciphertext
}

// key:32位长度
func AesDecrypt(src, key string) []byte {
	c, err := aes.NewCipher([]byte(key))
	if err != nil {
		fmt.Printf("Error: NewCipher(%d bytes) = %s", len(key), err)
		os.Exit(-1)
	}
	encrypttext := []byte(src)
	// 解密
	cfbdec := cipher.NewCFBDecrypter(c, commonIV)
	ciphertext := make([]byte, len(encrypttext))
	cfbdec.XORKeyStream(ciphertext, encrypttext)
	return ciphertext
}

func AesEncryptTest() {
	src := "welcome to 2021,and just say good byte to 2020 soon!"
	key := "nicero@2di$2020nicegowa#ow.89hGH"
	res := AesEncrypt(src, key)
	fmt.Println("aes encrypting ...")
	fmt.Printf("%s=>%x\n", src, res)
	fmt.Printf("%x=>%s\n", res, AesDecrypt(string(res), key))
}
